/**
  ETFDAQ Project
  \class TACAENCard
  \brief A VME card produced by CAEN Corp. from Italy
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-08-13
  \date 2024-08-13 last modified

  \copyright Copyright (c) 2024 IMP-CAS with LGPLv3 LICENSE
*/

#ifndef TACAENCard_h
#define TACAENCard_h

#include "TACard.h"

class TACAENCard : public TACard{
public:
  TACAENCard(TAController *ctrl, const TAYaml &c);
  virtual ~TACAENCard();

  ///--- initialization ---///
  virtual void Initialize() override;
  virtual void Identify() override; ///< read card info (e.g. serialNo.)
  virtual void SlotInit() override; ///< write slot id and crate id
  /// \param level 1~7, 0 will disable the IRQ generation
  /// \param vector 0x00~0xFF, requested by vme ctrler to identify the interrupter
  /// \param nEv: trigger will be generated after nof buffered events reaches nEv
  virtual void ConfigIRQ(int level, int vector, int nEv) const override;

  ///--- configuration ---///
  /// to select to write the header and EOB (End of Block)
  /// anyway when there are no accepted channels
  virtual void EnableEmpty() const override;
  virtual void EnableBerr() const override;
  /// the following 2 methods enable or disable certain ch(s)
  /// by set the KILL bit of the ch threshold to 1
  /// \param ch starts from 0, -1 means all channels
  virtual void SetChOn(int ch = -1, bool opt = true) const override;
  /// \param ch starts from 0, -1 means all channels
  /// only the first 8 bits in thre are valid by default
  /// kill bit in thre: 1 will kill; while 0 takes no effect, the original killbit
  /// in the register is preserved
  virtual void SetThreshold(int ch, uint16_t thre) const override;
  virtual void SetIped(int iped) const override; ///< set pedestal current for qdcs
  /// true: thre*2; false(default): thre*16
  virtual void UsingSmallThre(bool opt = true) const override;
  /// overflow and zero suppressions
  virtual void KeepUnderflow(bool opt = true) const override;
  virtual void KeepOverflow(bool opt = true) const override;
  /// data reset(DR), software reset(SR) and hardware reset(HR) are different
  /// Please refer to the register map to check what they resets respectively
  /// usually DR only resets data, ev counters and read/write pointers
  /// SR is DR plus reset of most of the controlling registers
  /// HR is SR plus all the resetable registers
  virtual void SoftwareReset() override;
  /// this function let the card send all data until the first EOB (end of event)
  /// then it sends no data. It is realized via setting the Control1 register
  /// The card generates a BERR error to finish the block transfer
  virtual void SetReadOneEvent() const override;

  ///--- the DAQ loop ---///
  virtual bool DataReady() const override; ///< true if buffered events are enough
  /// read all events in the buffer \retval nof words read
  virtual int ReadData(uint32_t *buf) override;
  /// read one event in the buffer \retval nof words read
  virtual int ReadEvent(uint32_t *buf) override;
  /// clear the module's multi-event buffers, the R/W pointers, and the event counters
  virtual void ClearData() override; // data reset (DR)
  virtual void ClearEventCounter() override; // clears the event counter
  /// event counter increments on all trigs (true) or only accepted trigs (false)
  virtual void SetAllTrigger(bool opt) const override;

  /// ---- print functions ---///
  virtual void Print() const override;
  /// \return the event counter register
  virtual void ReadEventCounter() override;
  virtual void PrintEvent(const uint32_t *ev)  override; ///< print one event
};

#endif
